package org.onvivals.admin.module.auth.controller;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.onvivals.admin.module.auth.form.LoginForm;
import org.onvivals.admin.module.auth.param.UpdatePasswordParam;
import org.onvivals.admin.module.auth.service.ICaptchaService;
import org.onvivals.common.enums.MenuType;
import org.onvivals.common.exception.BusinessException;
import org.onvivals.common.utils.CommonUtil;
import org.onvivals.common.utils.RedisUtils;
import org.onvivals.common.web.Result;
import org.onvivals.module.system.entity.SysMenu;
import org.onvivals.module.system.entity.SysUser;
import org.onvivals.module.system.entity.vo.LoginVo;
import org.onvivals.module.system.service.ISysMenuService;
import org.onvivals.module.system.service.ISysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Slf4j
@Tag(name = "认证模块")
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthController {

    private final ICaptchaService captchaService;
    private final ISysUserService sysUserService;
    private final ISysMenuService sysMenuService;
    private final RedisUtils redisUtils;

    /**
     * 获取验证码
     */
    @Operation(summary = "获取验证码")
    @GetMapping("/captcha")
    public Result<?> captcha(HttpServletResponse response) throws IOException {
        //生成验证码
        Map<String, Object> map = captchaService.create(response);
        return Result.ok(map);
    }

    /**
     * 账户密码登录
     */
    @Operation(summary = "登录接口")
    @PostMapping("/login")
    public Result<?> login(@RequestBody LoginForm login) {
        // 查询验证码
        String code = (String) redisUtils.get(login.getUuid());
        log.info("验证码:{}", code);
        // 清除验证码
        redisUtils.del(login.getUuid());
        if (StrUtil.isBlank(code)) {
            throw new BusinessException("验证码不存在或已过期");
        }
        if (StrUtil.isBlank(login.getCaptcha()) || !login.getCaptcha().equalsIgnoreCase(code)) {
            throw new BusinessException("验证码错误");
        }
        SysUser sysUser = sysUserService.getByUsername(login.getUsername());
        //1. 校验用户是否有效
        sysUserService.checkUserIsEffective(sysUser);
        //2. 校验用户名或密码是否正确
        String userPassword = SaSecureUtil.md5BySalt(login.getPassword(), sysUser.getSalt());
        log.info("密码：{}", userPassword);
        String assessorPassword = sysUser.getPassword();
        log.info("用户密码:{}", assessorPassword);
        if (!assessorPassword.equals(userPassword)) {
            String message = "用户名或密码错误";
            return Result.error(message);
        }
        Console.log(JSONUtil.toJsonStr(sysUser));
        //登陆
        StpUtil.login(sysUser.getUserId(), login.isRemember());
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        LoginVo loginVo = new LoginVo();
        loginVo.setUser(sysUser);
        loginVo.setSaTokenInfo(tokenInfo);
        log.info("用户：{}，登陆成功", sysUser.getUsername());
        return Result.OK("登陆成功", loginVo);
    }

    /**
     * 获取当前登陆人信息
     */
    @Operation(summary = "获取登录用户信息")
    @GetMapping("/user")
    public Result<SysUser> userInfo() {
        Long loginId = StpUtil.getLoginIdAsLong();
        SysUser sysUserVo = sysUserService.getByUserId(loginId);
        return Result.OK("获取成功", sysUserVo);
    }

    @Operation(summary ="获取登录用户菜单")
    @GetMapping("/menu")
    public Result<List<SysMenu>> userMenu() {
        long loginId = StpUtil.getLoginIdAsLong();
        List<SysMenu> menus = sysMenuService.listMenuByUserId(loginId, MenuType.MENU.getValue());
        return Result.OK("获取登录用户菜单", CommonUtil.toTreeData(menus, 0L, SysMenu::getParentId, SysMenu::getMenuId, SysMenu::setChildren));
    }

    @Operation(summary ="修改自己密码")
    @PutMapping("/password")
    public Result<?> updatePassword(@RequestBody UpdatePasswordParam param) {
        if (StrUtil.hasBlank(param.getOldPassword(), param.getPassword())) {
            return Result.error("参数不能为空");
        }
        Long userId = StpUtil.getLoginIdAsLong();
        SysUser user1 = sysUserService.getById(userId);
        String password = user1.getPassword();
        log.info("用户密码:{}", password);
        String salt = user1.getSalt();
        String assessorPassword = param.getOldPassword();
        String oldPassword = SaSecureUtil.md5BySalt(assessorPassword, salt);
        log.info("用户密码:{}", oldPassword);
        if (!oldPassword.equals(password)) {
            String message = "原密码输入不正确";
            return Result.error(message);
        }
        SysUser user = new SysUser();
        user.setUserId(userId);
        String pwd = SaSecureUtil.md5BySalt(param.getPassword(), salt);
        user.setPassword(pwd);
        if (sysUserService.updateById(user)) {
            return Result.ok("修改成功");
        }
        return Result.error("修改失败");
    }

    /**
     * 退出登陆
     */
    @Operation(summary = "退出登陆")
    @GetMapping("/logout")
    public Result<?> logout() {
        StpUtil.logout();
        return Result.OK("退出成功");
    }

}
